import {environment} from '../../../environments/environment';
import {CookieHelper} from '../../shared/utils/cookie-helper';
import {catchError, map} from 'rxjs/operators';
import {of} from 'rxjs/internal/observable/of';
import {Injectable} from '@angular/core';
//TODO
// import {stringify} from 'querystring';
import {CommonService} from './common.service';
import {ObjectUtil} from '../../shared/utils/object-util';
import {CacheKey, CookieKey} from '../../shared/components/dhlcomponent/enums';

@Injectable()
export class RequestService extends CommonService {


  private ResponseFormat = {
    RETURN_CODE: 'code',
    RETURN_MESSAGE: 'msg',
    RETURN_DATA: 'data',
  };
  private notifyTypes = {
    ALERT: 'alert',
    MESSAGE: 'message',
    NOTIFY: 'notify',
  };
  private msgType = {
    SUCCESS: 'success',
    INFO: 'info',
    ERROR: 'error',
  };

  private ResponseStatus = {
    SUCCESS: 0,
    ERROR: -1,
    INFO: -2,
    UNAUTHORIZED: 1,
    INVALID_TOKEN: 2,
    TOKEN_EXPIRED: 6,
    SERVER_ERROR: 500,
    GATEWAY_ERROR: 502,
    TIME_OUT: 504,
    NOT_FOUND_ERROR: 404,
    SC_UNAUTHORIZED: 401,
    SC_FORBIDDEN: 403,
    REQUEST_EXCEPTION: 400
  };


  post(url, ...params) {
    return this.request(url, ObjectUtil.isNotEmpty(params) ? params[0] : null, 'POST');
  }

  get(url, ...params) {
    return this.request(url, ObjectUtil.isNotEmpty(params) ? params[0] : null, 'GET');
  }

  requestPost(url, ...params) {

    url = this.getRequestUrl(url);

    const menu = this.cacheService.getItem(CacheKey.ACTIVE_MENU);
    const {code: roleCode, name: roleName} = this.cacheService.getItem(CacheKey.ACTIVE_ROLE);

    if (menu) {
      const defaultParam = `menu=${menu.name}&activeRoleCode=${roleCode}&activeRoleName=${roleName}`;
      const tempParams = url.split('?');
      if (tempParams.length > 1) {
        tempParams[1] += `&${defaultParam}`;
        url = tempParams[0] + '?' + tempParams[1];
      } else {
        url += `?${defaultParam}`;
      }

    }

    return this.httpClient.request('POST', url, {
      headers: this.getDefaultHeaders(),
      withCredentials: true,
      body: params
    }).pipe(
      map(response => {
        console.log(`${url} 返回的response结果：`, response);
        // @ts-ignore
        const {data, code, msg, type} = response;
        if (code && code == 2) {
          const preUrl = this.router.url;
          if (preUrl != '/login') {
            CookieHelper.set(CookieKey.REQUEST_PAGE, this.router.url);
          }
          this.router.navigateByUrl('/login');
        } else if (this.ResponseStatus.INFO == code) {
          this.messageService.info(msg);
          return false;
        }

        if (this.checkResponseFormat(response, url) && this.checkSecurity(response, url)) {
          if (
            (ObjectUtil.isArray(data) && data.length == 0) ||
            (ObjectUtil.isObject(data) && Object.keys(data).length == 0
            )) {
            return false;
          } else {
            return data;
          }
        } else {
          return false;
        }
      }),
      catchError(obj => {

        let errorMsg = '';
        let errorCode = '';
        let errorStatus = '';
        if (obj.status) {
          if (this.ResponseStatus.NOT_FOUND_ERROR == obj.status) {
            errorMsg = `http请求路径没有找到`;
            errorCode = obj.name || '';
            errorStatus = obj.status || '';
          } else if (this.ResponseStatus.GATEWAY_ERROR == obj.status) {
            errorMsg = `服务器可能未启动`;
            errorCode = obj.name || '';
            errorStatus = obj.status || '';
          } else if (this.ResponseStatus.REQUEST_EXCEPTION == obj.status) {
            errorMsg = `request请求异常`;
            errorCode = obj.name || '';
            errorStatus = obj.status || '';
          } else if (this.ResponseStatus.TIME_OUT == obj.status) {
            errorMsg = `请求超时`;
            errorCode = obj.name || '';
            errorStatus = obj.status || '';
          } else if (this.ResponseStatus.SC_UNAUTHORIZED == obj.status) {
            CookieHelper.clearCookies();
            this.router.navigateByUrl('/login');
            return of(false);
          } else {
            const {error: {msg}} = obj;
            errorMsg = msg;
          }
        } else {
          errorMsg = obj.message || '';
        }
        this.messageService.notifyError(`${url}<br/>${errorCode}<br/>${errorMsg}`, `request异常${errorStatus == '' ? '' : '-' + errorStatus}`);
        return of(false);
      })
    );
  }


  downloadByFilePath(filePath) {
    const appCode = environment.appCode;
    this.download(`/${appCode}/attachment/download`, {filePath});
  }

  download(url, ...params) {
    const requestUrl = super.getRequestUrl(url);
    window.location.href = ObjectUtil.isNotEmpty(params) ? requestUrl + `?` : requestUrl;
    // window.location.href = ObjectUtil.isNotEmpty(params) ? requestUrl + `?${stringify(params[0])}` : requestUrl;
  }

  private request(url, params, method) {
    if (!ObjectUtil.isHaveValue(url)) {
      this.messageService.info('请输入rul参数');
      return;
    }

    let joinParams = '';
    const newParams = this.filterNullParams(params);
    const menu = this.cacheService.getItem(CacheKey.ACTIVE_MENU);
    const role = this.cacheService.getItem(CacheKey.ACTIVE_ROLE);


    if (menu) {
      newParams['menu'] = menu.name;
    }


    if (role) {
      const {code: roleCode, name: roleName} = role;
      newParams['activeRoleCode'] = roleCode;
      newParams['activeRoleName'] = roleName;
    }


    for (const key of Object.keys(newParams)) {
      const value = newParams[key]
      if (ObjectUtil.isArray(value)) {
        const newArrayValue = [];
        let temp: any;
        temp = value;
        for (const v of temp) {
          newArrayValue.push(encodeURIComponent(v));
        }
        joinParams += (key + '=' + newArrayValue + '&');
      } else {
        // @ts-ignore
        joinParams += (key + '=' + encodeURIComponent(value) + '&');
      }

    }

    joinParams = joinParams.substr(0, joinParams.length - 1)

    url = this.getRequestUrl(url) + '?' + joinParams;

    return this.httpClient.request(method, url, {
      headers: this.getDefaultHeaders(),
      withCredentials: true
    }).pipe(
      map(response => {
        console.log(`${url} 返回的response结果：`, response);
        // @ts-ignore
        const {data, code, msg, type} = response;
        if (code && code == 2) {
          const preUrl = this.router.url;
          if (preUrl != '/login') {
            CookieHelper.set(CookieKey.REQUEST_PAGE, this.router.url);
          }
          this.router.navigateByUrl('/login');
        } else if (this.ResponseStatus.INFO == code) {
          this.messageService.info(msg);
          return false;
        }

        if (this.checkResponseFormat(response, url) && this.checkSecurity(response, url)) {
          if (
            (ObjectUtil.isArray(data) && data.length == 0) ||
            (ObjectUtil.isObject(data) && Object.keys(data).length == 0
            )) {
            return false;
          } else {
            return data;
          }
        } else {
          return false;
        }
      }),
      catchError(obj => {

        let errorMsg = '';
        let errorCode = '';
        let errorStatus = '';
        if (obj.status) {
          if (this.ResponseStatus.NOT_FOUND_ERROR == obj.status) {
            errorMsg = `http请求路径没有找到`;
            errorCode = obj.name || '';
            errorStatus = obj.status || '';
          } else if (this.ResponseStatus.GATEWAY_ERROR == obj.status) {
            errorMsg = `服务器可能未启动`;
            errorCode = obj.name || '';
            errorStatus = obj.status || '';
          } else if (this.ResponseStatus.REQUEST_EXCEPTION == obj.status) {
            errorMsg = `request请求异常`;
            errorCode = obj.name || '';
            errorStatus = obj.status || '';
          } else if (this.ResponseStatus.TIME_OUT == obj.status) {
            errorMsg = `请求超时`;
            errorCode = obj.name || '';
            errorStatus = obj.status || '';
          } else if (this.ResponseStatus.SC_UNAUTHORIZED == obj.status) {
            CookieHelper.clearCookies();
            this.router.navigateByUrl('/login');
            return of(false);
          } else {
            const {error: {msg}} = obj;
            errorMsg = msg;
          }
        } else {
          errorMsg = obj.message || '';
        }
        this.messageService.notifyError(`${url}<br/>${errorCode}<br/>${errorMsg}`, `request异常${errorStatus == '' ? '' : '-' + errorStatus}`);
        return of(false);
      })
    );

  }


  private getToken(): string {
    const result = CookieHelper.get(environment.tokenCookieKey);
    return !!result ? result : '';
  }

  private getDefaultHeaders() {
    let acceptLanguage = CookieHelper.get(environment.languageCookieKey);
    if (!acceptLanguage) {
      acceptLanguage = environment.defaultLanguage;
    }

    const token = this.getToken();
    const result = {
      'Content-Type': 'application/json',
      'Accept-Language': acceptLanguage,
      Accept: 'application/json',
      Authorization: 'Bearer ' + token,
      token
    };
    return result;
  }

  private filterNullParams(queryParams) {
    if (!queryParams) {
      return {};
    }

    const paramNames = Object.getOwnPropertyNames(queryParams);
    const paramObj = {};
    if (ObjectUtil.isNotEmpty(paramNames)) {
      paramNames
        .filter(p => ObjectUtil.isHaveValue(queryParams[p]))
        .forEach(p => paramObj[p] = queryParams[p]);
    }

    return paramObj;
  }


  private checkResponseFormat = (obj, relativeUrl) => {

    const {code, msg, notifyType, msgType} = obj;
    if (ObjectUtil.isObject(obj)) {
      if (obj.hasOwnProperty(this.ResponseFormat.RETURN_CODE)
        && obj.hasOwnProperty(this.ResponseFormat.RETURN_MESSAGE)
        && obj.hasOwnProperty(this.ResponseFormat.RETURN_DATA)) {
        if (code == this.ResponseStatus.SERVER_ERROR) {
          this.messageService.notifyError(msg, '后台异常');
          return false;
        } else if (notifyType == this.notifyTypes.NOTIFY) {
          if (msgType == this.msgType.INFO) {
            this.messageService.notifyInfo(msg);
          } else if (msgType == this.msgType.ERROR) {
            this.messageService.notifyError(msg);
          } else if (msgType == this.msgType.SUCCESS) {
            this.messageService.notifySuccess(msg);
          }
        } else if (notifyType == this.notifyTypes.ALERT) {
          this.messageService.openAlert(msg);
        } else if (notifyType == this.notifyTypes.MESSAGE) {
          if (msgType == this.msgType.INFO) {
            this.messageService.info(msg);
          } else if (msgType == this.msgType.ERROR) {
            this.messageService.error(msg);
          } else if (msgType == this.msgType.SUCCESS) {
            this.messageService.success(msg);
          }
        } else {
          return true;
        }
      } else {
        this.messageService.notifyError(`${relativeUrl} <br/>返回的数据结构不对, 要求有这几个属性 id,data,msg`, 'response格式不正确');
        return false;
      }
    } else {
      this.messageService.notifyError(`${relativeUrl} <br/>异常报错, 详细信息请看后台日志`, 'request请求异常');
      return false;
    }
  };

  private checkSecurity = (response, url) => {

    const {code, data, msg} = response;

    if (code === this.ResponseStatus.INVALID_TOKEN || code === this.ResponseStatus.TOKEN_EXPIRED) {
      // this.redirectToLoginPage();
      return;
    } else if (code === this.ResponseStatus.ERROR) {
      this.messageService.notifyError(url + '<br/>' + msg);
      return;
    }
    return true;
  };

}


